字数
458 字
阅读时间
2 分钟
一开始在 JS 的任务队列那块,不理解为什么 script 算作宏任务,然后仔细 google 了下,才恍然大悟
从代码入手分析
代码一
js
<!-- 脚本 1 -->
<script>
// 同步
console.log('start1')
// 异步宏
setTimeout(() => console.log('timer1'), 0)
new Promise((resolve, reject) => {
// 同步
console.log('p1')
resolve()
}).then(() => {
// 异步微
console.log('then1')
})
// 同步
console.log('end1')
</script>
<!-- 脚本 2 -->
<script>
// 同步
console.log('start2')
// 异步宏
setTimeout(() => console.log('timer2'), 0)
new Promise((resolve, reject) => {
// 同步
console.log('p2')
resolve()
}).then(() => {
// 异步微
console.log('then2')
})
// 同步
console.log('end2')
</script>执行结果:
可能有部分同学不理解为什么 timer1 在 脚本 2 后才输出,这是因为他们把一个 标签理解成一个独立的运行环境,事实显然不是这样,再看一个代码
代码二
js
setTimeout(() => {
// 同步
console.log('start1')
// 异步宏
setTimeout(() => console.log('timer1'), 0)
new Promise((resolve, reject) => {
// 同步
console.log('p1')
resolve()
}).then(() => {
// 异步微
console.log('then1')
})
// 同步
console.log('end1')
}, 0)
setTimeout(() => {
// 同步
console.log('start2')
// 异步宏
setTimeout(() => console.log('timer2'), 0)
new Promise((resolve, reject) => {
// 同步
console.log('p2')
resolve()
}).then(() => {
// 异步微
console.log('then2')
})
// 同步
console.log('end2')
}, 0)执行结果:
上述结果表明, 和 setTimeout 一样,都是宏任务
代码一的执行逻辑:
先将两个 script 代码压入任务队列中,根据出队顺序,排前面的 script 先执行,执行其内部的【同】,遇到 timer1 压入任务队列的宏任务中(此时宏队列中已经有下一个 script 存在),然后遇到 then1 后压入微队列
然后执行微队列,then1 输出,从宏队列拿出第一个,也就是 script2,同理,遇到 timer2 后也压入宏队列(此时宏队列:timer1, timer2),然后输出 then2
最后再执行宏队列的 timer1, timer2